home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / span.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-04  |  30.7 KB  |  1,148 lines

  1. /* $Id: span.c,v 3.9 1998/08/16 14:45:44 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: span.c,v $
  26.  * Revision 3.9  1998/08/16 14:45:44  brianp
  27.  * fixed clipping problem in gl_read_rgba_span() (Karl Schultz)
  28.  *
  29.  * Revision 3.8  1998/06/07 22:18:52  brianp
  30.  * implemented GL_EXT_multitexture extension
  31.  *
  32.  * Revision 3.7  1998/03/28 03:57:13  brianp
  33.  * added CONST macro to fix IRIX compilation problems
  34.  *
  35.  * Revision 3.6  1998/03/27 04:17:31  brianp
  36.  * fixed G++ warnings
  37.  *
  38.  * Revision 3.5  1998/03/15 17:55:54  brianp
  39.  * added FogMode to context struct
  40.  *
  41.  * Revision 3.4  1998/03/10 01:27:47  brianp
  42.  * fixed bugs in the backup of color arrays
  43.  *
  44.  * Revision 3.3  1998/02/20 04:50:44  brianp
  45.  * implemented GL_SGIS_multitexture
  46.  *
  47.  * Revision 3.2  1998/02/03 04:26:07  brianp
  48.  * removed const from lambda[] passed to gl_write_texture_span()
  49.  *
  50.  * Revision 3.1  1998/02/02 03:09:34  brianp
  51.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  52.  *
  53.  * Revision 3.0  1998/01/31 21:03:42  brianp
  54.  * initial rev
  55.  *
  56.  */
  57.  
  58.  
  59. /*
  60.  * pixel span rasterization:
  61.  * These functions simulate the rasterization pipeline.
  62.  */
  63.  
  64.  
  65. #ifdef PC_HEADER
  66. #include "all.h"
  67. #else
  68. #include <assert.h>
  69. #include <string.h>
  70. #include "alpha.h"
  71. #include "alphabuf.h"
  72. #include "blend.h"
  73. #include "depth.h"
  74. #include "fog.h"
  75. #include "logic.h"
  76. #include "macros.h"
  77. #include "masking.h"
  78. #include "scissor.h"
  79. #include "span.h"
  80. #include "stencil.h"
  81. #include "texture.h"
  82. #include "types.h"
  83. #endif
  84.  
  85.  
  86.  
  87.  
  88. /*
  89.  * Apply the current polygon stipple pattern to a span of pixels.
  90.  */
  91. static void stipple_polygon_span( GLcontext *ctx,
  92.                   GLuint n, GLint x, GLint y, GLubyte mask[] )
  93. {
  94.    register GLuint i, m, stipple, highbit=0x80000000;
  95.  
  96.    stipple = ctx->PolygonStipple[y % 32];
  97.    m = highbit >> (GLuint) (x % 32);
  98.  
  99.    for (i=0;i<n;i++) {
  100.       if ((m & stipple)==0) {
  101.      mask[i] = 0;
  102.       }
  103.       m = m >> 1;
  104.       if (m==0) {
  105.      m = 0x80000000;
  106.       }
  107.    }
  108. }
  109.  
  110.  
  111.  
  112. /*
  113.  * Clip a pixel span to the current buffer/window boundaries.
  114.  * Return:  0 = all pixels clipped
  115.  *          1 = at least one pixel is visible
  116.  */
  117. static GLuint clip_span( GLcontext *ctx,
  118.              GLint n, GLint x, GLint y, GLubyte mask[] )
  119. {
  120.    GLint i;
  121.  
  122.    /* Clip to top and bottom */
  123.    if (y<0 || y>=ctx->Buffer->Height) {
  124.       return 0;
  125.    }
  126.  
  127.    /* Clip to left and right */
  128.    if (x>=0 && x+n<=ctx->Buffer->Width) {
  129.       /* no clipping needed */
  130.       return 1;
  131.    }
  132.    else if (x+n<=0) {
  133.       /* completely off left side */
  134.       return 0;
  135.    }
  136.    else if (x>=ctx->Buffer->Width) {
  137.       /* completely off right side */
  138.       return 0;
  139.    }
  140.    else {
  141.       /* clip-test each pixel, this could be done better */
  142.       for (i=0;i<n;i++) {
  143.      if (x+i<0 || x+i>=ctx->Buffer->Width) {
  144.         mask[i] = 0;
  145.      }
  146.       }
  147.       return 1;
  148.    }
  149. }
  150.  
  151.  
  152.  
  153. /*
  154.  * Write a horizontal span of color index pixels to the frame buffer.
  155.  * Stenciling, Depth-testing, etc. are done as needed.
  156.  * Input:  n - number of pixels in the span
  157.  *         x, y - location of leftmost pixel in the span
  158.  *         z - array of [n] z-values
  159.  *         index - array of [n] color indexes
  160.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  161.  */
  162. void gl_write_index_span( GLcontext *ctx,
  163.               GLuint n, GLint x, GLint y, const GLdepth z[],
  164.               GLuint indexIn[], GLenum primitive )
  165. {
  166.    GLubyte mask[MAX_WIDTH];
  167.    GLuint indexBackup[MAX_WIDTH];
  168.    GLuint *index;  /* points to indexIn or indexBackup */
  169.  
  170.    /* init mask to 1's (all pixels are to be written) */
  171.    MEMSET(mask, 1, n);
  172.  
  173.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  174.       if (clip_span(ctx,n,x,y,mask)==0) {
  175.      return;
  176.       }
  177.    }
  178.  
  179.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  180.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  181.       /* Make copy of color indexes */
  182.       MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
  183.       index = indexBackup;
  184.    }
  185.    else {
  186.       index = indexIn;
  187.    }
  188.  
  189.    /* Per-pixel fog */
  190.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode == FOG_FRAGMENT)) {
  191.       gl_fog_ci_pixels( ctx, n, z, index );
  192.    }
  193.  
  194.    /* Do the scissor test */
  195.    if (ctx->Scissor.Enabled) {
  196.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  197.      return;
  198.       }
  199.    }
  200.  
  201.    /* Polygon Stippling */
  202.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  203.       stipple_polygon_span( ctx, n, x, y, mask );
  204.    }
  205.  
  206.    if (ctx->Stencil.Enabled) {
  207.       /* first stencil test */
  208.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  209.      return;
  210.       }
  211.       /* depth buffering w/ stencil */
  212.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  213.    }
  214.    else if (ctx->Depth.Test) {
  215.       /* regular depth testing */
  216.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  217.    }
  218.  
  219.    if (ctx->RasterMask & NO_DRAW_BIT) {
  220.       /* write no pixels */
  221.       return;
  222.    }
  223.  
  224.    if (ctx->Color.SWLogicOpEnabled) {
  225.       gl_logicop_ci_span( ctx, n, x, y, index, mask );
  226.    }
  227.    if (ctx->Color.SWmasking) {
  228.       gl_mask_index_span( ctx, n, x, y, index );
  229.    }
  230.  
  231.    /* write pixels */
  232.    (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
  233.  
  234.  
  235.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  236.       /*** Also draw to back buffer ***/
  237.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  238.       MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
  239.       assert( index == indexBackup );
  240.       if (ctx->Color.SWLogicOpEnabled) {
  241.      gl_logicop_ci_span( ctx, n, x, y, index, mask );
  242.       }
  243.       if (ctx->Color.SWmasking) {
  244.      gl_mask_index_span( ctx, n, x, y, index );
  245.       }
  246.       (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
  247.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  248.    }
  249. }
  250.  
  251.  
  252.  
  253.  
  254. void gl_write_monoindex_span( GLcontext *ctx,
  255.                   GLuint n, GLint x, GLint y, const GLdepth z[],
  256.                   GLuint index, GLenum primitive )
  257. {
  258.    GLuint i;
  259.    GLubyte mask[MAX_WIDTH];
  260.    GLuint indexBackup[MAX_WIDTH];
  261.  
  262.    /* init mask to 1's (all pixels are to be written) */
  263.    MEMSET(mask, 1, n);
  264.  
  265.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  266.       if (clip_span( ctx, n, x, y, mask)==0) {
  267.      return;
  268.       }
  269.    }
  270.  
  271.    /* Do the scissor test */
  272.    if (ctx->Scissor.Enabled) {
  273.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  274.      return;
  275.       }
  276.    }
  277.  
  278.    /* Polygon Stippling */
  279.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  280.       stipple_polygon_span( ctx, n, x, y, mask );
  281.    }
  282.  
  283.    if (ctx->Stencil.Enabled) {
  284.       /* first stencil test */
  285.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  286.      return;
  287.       }
  288.       /* depth buffering w/ stencil */
  289.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  290.    }
  291.    else if (ctx->Depth.Test) {
  292.       /* regular depth testing */
  293.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  294.    }
  295.  
  296.    if (ctx->RasterMask & NO_DRAW_BIT) {
  297.       /* write no pixels */
  298.       return;
  299.    }
  300.  
  301.    if ((ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT))
  302.     || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
  303.       GLuint ispan[MAX_WIDTH];
  304.       /* index may change, replicate single index into an array */
  305.       for (i=0;i<n;i++) {
  306.      ispan[i] = index;
  307.       }
  308.  
  309.       if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  310.      gl_fog_ci_pixels( ctx, n, z, ispan );
  311.       }
  312.  
  313.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  314.      MEMCPY( indexBackup, ispan, n * sizeof(GLuint) );
  315.       }
  316.  
  317.       if (ctx->Color.SWLogicOpEnabled) {
  318.      gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  319.       }
  320.  
  321.       if (ctx->Color.SWmasking) {
  322.      gl_mask_index_span( ctx, n, x, y, ispan );
  323.       }
  324.  
  325.       (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, ispan, mask );
  326.  
  327.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  328.      /*** Also draw to back buffer ***/
  329.      MEMCPY( ispan, indexBackup, n * sizeof(GLuint) );
  330.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  331.      for (i=0;i<n;i++) {
  332.         ispan[i] = index;
  333.      }
  334.      if (ctx->Color.SWLogicOpEnabled) {
  335.         gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  336.      }
  337.      if (ctx->Color.SWmasking) {
  338.         gl_mask_index_span( ctx, n, x, y, ispan );
  339.      }
  340.      (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, ispan, mask );
  341.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  342.       }
  343.    }
  344.    else {
  345.       (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
  346.  
  347.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  348.      /*** Also draw to back buffer ***/
  349.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  350.      (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
  351.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  352.       }
  353.    }
  354. }
  355.  
  356.  
  357. void gl_write_rgba_span( GLcontext *ctx,
  358.              GLuint n, GLint x, GLint y, const GLdepth z[],
  359.              GLubyte rgbaIn[][4],
  360.              GLenum primitive )
  361. {
  362.    GLubyte mask[MAX_WIDTH];
  363.    GLboolean write_all = GL_TRUE;
  364.    GLubyte rgbaBackup[MAX_WIDTH][4];
  365.    GLubyte (*rgba)[4];
  366.    const GLubyte *Null = 0;
  367.  
  368.    /* init mask to 1's (all pixels are to be written) */
  369.    MEMSET(mask, 1, n);
  370.  
  371.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  372.       if (clip_span( ctx,n,x,y,mask)==0) {
  373.      return;
  374.       }
  375.       write_all = GL_FALSE;
  376.    }
  377.  
  378.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  379.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  380.       /* must make a copy of the colors since they may be modified */
  381.       MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
  382.       rgba = rgbaBackup;
  383.    }
  384.    else {
  385.       rgba = rgbaIn;
  386.    }
  387.  
  388.    /* Per-pixel fog */
  389.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  390.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  391.    }
  392.  
  393.    /* Do the scissor test */
  394.    if (ctx->Scissor.Enabled) {
  395.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  396.      return;
  397.       }
  398.       write_all = GL_FALSE;
  399.    }
  400.  
  401.    /* Polygon Stippling */
  402.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  403.       stipple_polygon_span( ctx, n, x, y, mask );
  404.       write_all = GL_FALSE;
  405.    }
  406.  
  407.    /* Do the alpha test */
  408.    if (ctx->Color.AlphaEnabled) {
  409. #ifndef __STORM__
  410.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  411. #else
  412.       if (gl_alpha_test( ctx, n, (CONST GLubyte(*)[4])rgba, mask )==0) {
  413. #endif
  414.      return;
  415.       }
  416.       write_all = GL_FALSE;
  417.    }
  418.  
  419.    if (ctx->Stencil.Enabled) {
  420.       /* first stencil test */
  421.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  422.      return;
  423.       }
  424.       /* depth buffering w/ stencil */
  425.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  426.       write_all = GL_FALSE;
  427.    }
  428.    else if (ctx->Depth.Test) {
  429.       /* regular depth testing */
  430.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  431.       if (m==0) {
  432.      return;
  433.       }
  434.       if (m<n) {
  435.      write_all = GL_FALSE;
  436.       }
  437.    }
  438.  
  439.    if (ctx->RasterMask & NO_DRAW_BIT) {
  440.       /* write no pixels */
  441.       return;
  442.    }
  443.  
  444.    /* logic op or blending */
  445.    if (ctx->Color.SWLogicOpEnabled) {
  446.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  447.    }
  448.    else if (ctx->Color.BlendEnabled) {
  449.       gl_blend_span( ctx, n, x, y, rgba, mask );
  450.    }
  451.  
  452.    /* Color component masking */
  453.    if (ctx->Color.SWmasking) {
  454.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  455.    }
  456.  
  457.    /* write pixels */
  458. #ifndef __STORM__
  459.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  460. #else
  461.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  462. #endif
  463.    if (ctx->RasterMask & ALPHABUF_BIT) {
  464. #ifndef __STORM__
  465.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  466. #else
  467.       gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  468. #endif
  469.    }
  470.  
  471.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  472.       /*** Also render to back buffer ***/
  473.       MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
  474.       assert( rgba == rgbaBackup );
  475.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  476.       if (ctx->Color.SWLogicOpEnabled) {
  477.      gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  478.       }
  479.       else  if (ctx->Color.BlendEnabled) {
  480.      gl_blend_span( ctx, n, x, y, rgba, mask );
  481.       }
  482.       if (ctx->Color.SWmasking) {
  483.      gl_mask_rgba_span( ctx, n, x, y, rgba );
  484.       }
  485. #ifndef __STORM__
  486.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  487. #else
  488.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  489. #endif
  490.       if (ctx->RasterMask & ALPHABUF_BIT) {
  491.      ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  492. #ifndef __STORM__
  493.      gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  494. #else
  495.      gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  496. #endif
  497.      ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  498.       }
  499.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  500.    }
  501.  
  502. }
  503.  
  504.  
  505.  
  506. /*
  507.  * Write a horizontal span of color pixels to the frame buffer.
  508.  * The color is initially constant for the whole span.
  509.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  510.  * Input:  n - number of pixels in the span
  511.  *         x, y - location of leftmost pixel in the span
  512.  *         z - array of [n] z-values
  513.  *         r, g, b, a - the color of the pixels
  514.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  515.  */
  516. void gl_write_monocolor_span( GLcontext *ctx,
  517.                   GLuint n, GLint x, GLint y, const GLdepth z[],
  518.                   GLint r, GLint g, GLint b, GLint a,
  519.                   GLenum primitive )
  520. {
  521.    GLuint i;
  522.    GLubyte mask[MAX_WIDTH];
  523.    GLboolean write_all = GL_TRUE;
  524.    GLubyte rgba[MAX_WIDTH][4];
  525.    const GLubyte *Null = 0;
  526.  
  527.    /* init mask to 1's (all pixels are to be written) */
  528.    MEMSET(mask, 1, n);
  529.  
  530.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  531.       if (clip_span( ctx,n,x,y,mask)==0) {
  532.      return;
  533.       }
  534.       write_all = GL_FALSE;
  535.    }
  536.  
  537.    /* Do the scissor test */
  538.    if (ctx->Scissor.Enabled) {
  539.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  540.      return;
  541.       }
  542.       write_all = GL_FALSE;
  543.    }
  544.  
  545.    /* Polygon Stippling */
  546.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  547.       stipple_polygon_span( ctx, n, x, y, mask );
  548.       write_all = GL_FALSE;
  549.    }
  550.  
  551.    /* Do the alpha test */
  552.    if (ctx->Color.AlphaEnabled) {
  553.       for (i=0;i<n;i++) {
  554.      rgba[i][ACOMP] = a;
  555.       }
  556. #ifndef __STORM__
  557.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  558. #else
  559.       if (gl_alpha_test( ctx, n, (CONST GLubyte(*)[4])rgba, mask )==0) {
  560. #endif
  561.      return;
  562.       }
  563.       write_all = GL_FALSE;
  564.    }
  565.  
  566.    if (ctx->Stencil.Enabled) {
  567.       /* first stencil test */
  568.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  569.      return;
  570.       }
  571.       /* depth buffering w/ stencil */
  572.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  573.       write_all = GL_FALSE;
  574.    }
  575.    else if (ctx->Depth.Test) {
  576.       /* regular depth testing */
  577.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  578.       if (m==0) {
  579.      return;
  580.       }
  581.       if (m<n) {
  582.      write_all = GL_FALSE;
  583.       }
  584.    }
  585.  
  586.    if (ctx->RasterMask & NO_DRAW_BIT) {
  587.       /* write no pixels */
  588.       return;
  589.    }
  590.  
  591.    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
  592.        || ctx->Color.SWmasking) {
  593.       /* assign same color to each pixel */
  594.       for (i=0;i<n;i++) {
  595.      if (mask[i]) {
  596.         rgba[i][RCOMP] = r;
  597.         rgba[i][GCOMP] = g;
  598.         rgba[i][BCOMP] = b;
  599.         rgba[i][ACOMP] = a;
  600.      }
  601.       }
  602.       if (ctx->Color.SWLogicOpEnabled) {
  603.      gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  604.       }
  605.       else if (ctx->Color.BlendEnabled) {
  606.      gl_blend_span( ctx, n, x, y, rgba, mask );
  607.       }
  608.  
  609.       /* Color component masking */
  610.       if (ctx->Color.SWmasking) {
  611.      gl_mask_rgba_span( ctx, n, x, y, rgba );
  612.       }
  613.  
  614.       /* write pixels */
  615. #ifndef __STORM__
  616.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  617. #else
  618.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  619. #endif
  620.       if (ctx->RasterMask & ALPHABUF_BIT) {
  621. #ifndef __STORM__
  622.      gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  623. #else
  624.      gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  625. #endif
  626.       }
  627.  
  628.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  629.      /*** Also draw to back buffer ***/
  630.      for (i=0;i<n;i++) {
  631.         if (mask[i]) {
  632.            rgba[i][RCOMP] = r;
  633.            rgba[i][GCOMP] = g;
  634.            rgba[i][BCOMP] = b;
  635.            rgba[i][ACOMP] = a;
  636.         }
  637.      }
  638.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  639.      if (ctx->Color.SWLogicOpEnabled) {
  640.         gl_logicop_rgba_span( ctx, n, x, y, rgba, mask);
  641.      }
  642.      else if (ctx->Color.BlendEnabled) {
  643.         gl_blend_span( ctx, n, x, y, rgba, mask );
  644.      }
  645.      if (ctx->Color.SWmasking) {
  646.         gl_mask_rgba_span( ctx, n, x, y, rgba );
  647.      }
  648. #ifndef __STORM__
  649.      (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  650. #else
  651.      (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  652. #endif
  653.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  654.      if (ctx->RasterMask & ALPHABUF_BIT) {
  655.         ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  656. #ifndef __STORM__
  657.         gl_write_alpha_span( ctx, n, x, y, rgba,
  658.                  write_all ? Null : mask );
  659. #else
  660.         gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba,
  661.                  write_all ? Null : mask );
  662. #endif
  663.         ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  664.      }
  665.       }
  666.    }
  667.    else {
  668.       (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
  669.       if (ctx->RasterMask & ALPHABUF_BIT) {
  670.      gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? Null : mask );
  671.       }
  672.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  673.      /* Also draw to back buffer */
  674.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  675.      (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
  676.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  677.      if (ctx->RasterMask & ALPHABUF_BIT) {
  678.         ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  679.         gl_write_mono_alpha_span( ctx, n, x, y, a,
  680.                       write_all ? Null : mask );
  681.         ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  682.      }
  683.       }
  684.    }
  685. }
  686.  
  687.  
  688.  
  689. /*
  690.  * Add specular color to base color.  This is used only when
  691.  * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
  692.  */
  693. static void add_colors(GLuint n, GLubyte rgba[][4], CONST GLubyte specular[][4] )
  694. {
  695.    GLuint i;
  696.    for (i=0; i<n; i++) {
  697.       GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
  698.       GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
  699.       GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
  700.       rgba[i][RCOMP] = MIN2(r, 255);
  701.       rgba[i][GCOMP] = MIN2(g, 255);
  702.       rgba[i][BCOMP] = MIN2(b, 255);
  703.    }
  704. }
  705.  
  706. /*
  707.  * Write a horizontal span of textured pixels to the frame buffer.
  708.  * The color of each pixel is different.
  709.  * Alpha-testing, stenciling, depth-testing, and blending are done
  710.  * as needed.
  711.  * Input:  n - number of pixels in the span
  712.  *         x, y - location of leftmost pixel in the span
  713.  *         z - array of [n] z-values
  714.  *         s, t - array of (s,t) texture coordinates for each pixel
  715.  *         lambda - array of texture lambda values
  716.  *         rgba - array of [n] color components
  717.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  718.  */
  719. void gl_write_texture_span( GLcontext *ctx,
  720.                 GLuint n, GLint x, GLint y, const GLdepth z[],
  721.                 const GLfloat s[], const GLfloat t[],
  722.                 const GLfloat u[], GLfloat lambda[],
  723.                 GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  724.                 GLenum primitive )
  725. {
  726.    GLubyte mask[MAX_WIDTH];
  727.    GLboolean write_all = GL_TRUE;
  728.    GLubyte rgbaBackup[MAX_WIDTH][4];
  729.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  730.    const GLubyte *Null = 0;
  731.  
  732.    /* init mask to 1's (all pixels are to be written) */
  733.    MEMSET(mask, 1, n);
  734.  
  735.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  736.       if (clip_span(ctx, n, x, y, mask)==0) {
  737.      return;
  738.       }
  739.       write_all = GL_FALSE;
  740.    }
  741.  
  742.  
  743.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  744.       /* must make a copy of the colors since they may be modified */
  745.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  746.       rgba = rgbaBackup;
  747.    }
  748.    else {
  749.       rgba = rgbaIn;
  750.    }
  751.  
  752.    /* Texture */
  753.    ASSERT(ctx->Texture.Enabled);
  754.    gl_texture_pixels( ctx, 0, n, s, t, u, lambda, rgba );
  755.  
  756.    /* Add base and specular colors */
  757.    if (spec && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  758.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  759.  
  760.    /* Per-pixel fog */
  761.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  762.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  763.    }
  764.  
  765.    /* Do the scissor test */
  766.    if (ctx->Scissor.Enabled) {
  767.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  768.      return;
  769.       }
  770.       write_all = GL_FALSE;
  771.    }
  772.  
  773.    /* Polygon Stippling */
  774.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  775.       stipple_polygon_span( ctx, n, x, y, mask );
  776.       write_all = GL_FALSE;
  777.    }
  778.  
  779.    /* Do the alpha test */
  780.    if (ctx->Color.AlphaEnabled) {
  781.       if (gl_alpha_test( ctx, n, (CONST GLubyte(*)[4])rgba, mask )==0) {
  782.      return;
  783.       }
  784.       write_all = GL_FALSE;
  785.    }
  786.  
  787.    if (ctx->Stencil.Enabled) {
  788.       /* first stencil test */
  789.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  790.      return;
  791.       }
  792.       /* depth buffering w/ stencil */
  793.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  794.       write_all = GL_FALSE;
  795.    }
  796.    else if (ctx->Depth.Test) {
  797.       /* regular depth testing */
  798.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  799.       if (m==0) {
  800.      return;
  801.       }
  802.       if (m<n) {
  803.      write_all = GL_FALSE;
  804.       }
  805.    }
  806.  
  807.    if (ctx->RasterMask & NO_DRAW_BIT) {
  808.       /* write no pixels */
  809.       return;
  810.    }
  811.  
  812.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  813.       /* make backup of fragment colors */
  814.       MEMCPY( rgbaBackup, rgba, 4 * n * sizeof(GLubyte) );
  815.    }
  816.  
  817.    /* blending */
  818.    if (ctx->Color.SWLogicOpEnabled) {
  819.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  820.    }
  821.    else  if (ctx->Color.BlendEnabled) {
  822.       gl_blend_span( ctx, n, x, y, rgba, mask );
  823.    }
  824.  
  825.    if (ctx->Color.SWmasking) {
  826.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  827.    }
  828.  
  829.    /* write pixels */
  830. #ifndef __STORM__
  831.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  832. #else
  833.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  834. #endif
  835.    if (ctx->RasterMask & ALPHABUF_BIT) {
  836. #ifndef __STORM__
  837.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  838. #else
  839.       gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  840. #endif
  841.    }
  842.  
  843.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  844.       /* Also draw to back buffer */
  845.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  846.       if (ctx->Color.SWLogicOpEnabled) {
  847.      gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  848.       }
  849.       else if (ctx->Color.BlendEnabled) {
  850.      gl_blend_span( ctx, n, x, y, rgba, mask );
  851.       }
  852.       if (ctx->Color.SWmasking) {
  853.      gl_mask_rgba_span( ctx, n, x, y, rgba );
  854.       }
  855. #ifndef __STORM__
  856.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  857. #else
  858.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  859. #endif
  860.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  861.       if (ctx->RasterMask & ALPHABUF_BIT) {
  862.      ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  863. #ifndef __STORM__
  864.      gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  865. #else
  866.      gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  867. #endif
  868.      ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  869.       }
  870.    }
  871. }
  872.  
  873.  
  874.  
  875. /*
  876.  * As above but perform multiple stages of texture application.
  877.  * Input:  texSets - number of texture sets to apply
  878.  */
  879. void gl_write_multitexture_span( GLcontext *ctx, GLuint texSets,
  880.                  GLuint n, GLint x, GLint y, const GLdepth z[],
  881.                  CONST GLfloat s[][MAX_WIDTH],
  882.                  CONST GLfloat t[][MAX_WIDTH],
  883.                  CONST GLfloat u[][MAX_WIDTH],
  884.                  GLfloat lambda[][MAX_WIDTH],
  885.                  GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  886.                  GLenum primitive )
  887. {
  888.    GLubyte mask[MAX_WIDTH];
  889.    GLboolean write_all = GL_TRUE;
  890.    GLubyte rgbaBackup[MAX_WIDTH][4];
  891.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  892.    GLuint i;
  893.    const GLubyte *Null = 0;
  894.  
  895.    /* init mask to 1's (all pixels are to be written) */
  896.    MEMSET(mask, 1, n);
  897.  
  898.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  899.       if (clip_span(ctx, n, x, y, mask)==0) {
  900.      return;
  901.       }
  902.       write_all = GL_FALSE;
  903.    }
  904.  
  905.  
  906.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  907.       /* must make a copy of the colors since they may be modified */
  908.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  909.       rgba = rgbaBackup;
  910.    }
  911.    else {
  912.       rgba = rgbaIn;
  913.    }
  914.  
  915.    /* Texture */
  916.    ASSERT(ctx->Texture.Enabled);
  917.    ASSERT(texSets <= MAX_TEX_SETS);
  918.    for (i=0;i<texSets;i++) {
  919.       GLuint j = ctx->Texture.Set[i].TexCoordSet;
  920.       /* Evaluate i_th texture environment using the j_th set of
  921.        * texture coords
  922.        */
  923.       gl_texture_pixels( ctx, i, n, s[j], t[j], u[j], lambda[j], rgba );
  924.    }
  925.  
  926.  
  927.    /* Add base and specular colors */
  928.    if (spec && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  929.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  930.  
  931.    /* Per-pixel fog */
  932.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  933.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  934.    }
  935.  
  936.    /* Do the scissor test */
  937.    if (ctx->Scissor.Enabled) {
  938.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  939.      return;
  940.       }
  941.       write_all = GL_FALSE;
  942.    }
  943.  
  944.    /* Polygon Stippling */
  945.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  946.       stipple_polygon_span( ctx, n, x, y, mask );
  947.       write_all = GL_FALSE;
  948.    }
  949.  
  950.    /* Do the alpha test */
  951.    if (ctx->Color.AlphaEnabled) {
  952. #ifndef __STORM__
  953.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  954. #else
  955.       if (gl_alpha_test( ctx, n, (CONST GLubyte(*)[4])rgba, mask )==0) {
  956. #endif
  957.      return;
  958.       }
  959.       write_all = GL_FALSE;
  960.    }
  961.  
  962.    if (ctx->Stencil.Enabled) {
  963.       /* first stencil test */
  964.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  965.      return;
  966.       }
  967.       /* depth buffering w/ stencil */
  968.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  969.       write_all = GL_FALSE;
  970.    }
  971.    else if (ctx->Depth.Test) {
  972.       /* regular depth testing */
  973.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  974.       if (m==0) {
  975.      return;
  976.       }
  977.       if (m<n) {
  978.      write_all = GL_FALSE;
  979.       }
  980.    }
  981.  
  982.    if (ctx->RasterMask & NO_DRAW_BIT) {
  983.       /* write no pixels */
  984.       return;
  985.    }
  986.  
  987.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  988.       /* make backup of fragment colors */
  989.       MEMCPY( rgbaBackup, rgba, 4 * n * sizeof(GLubyte) );
  990.    }
  991.  
  992.    /* blending */
  993.    if (ctx->Color.SWLogicOpEnabled) {
  994.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  995.    }
  996.    else  if (ctx->Color.BlendEnabled) {
  997.       gl_blend_span( ctx, n, x, y, rgba, mask );
  998.    }
  999.  
  1000.    if (ctx->Color.SWmasking) {
  1001.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  1002.    }
  1003.  
  1004.    /* write pixels */
  1005. #ifndef __STORM__
  1006.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  1007. #else
  1008.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  1009. #endif
  1010.    if (ctx->RasterMask & ALPHABUF_BIT) {
  1011. #ifndef __STORM__
  1012.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  1013. #else
  1014.       gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  1015. #endif
  1016.    }
  1017.  
  1018.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  1019.       /* Also draw to back buffer */
  1020.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  1021.       if (ctx->Color.SWLogicOpEnabled) {
  1022.      gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  1023.       }
  1024.       else if (ctx->Color.BlendEnabled) {
  1025.      gl_blend_span( ctx, n, x, y, rgba, mask );
  1026.       }
  1027.       if (ctx->Color.SWmasking) {
  1028.      gl_mask_rgba_span( ctx, n, x, y, rgba );
  1029.       }
  1030. #ifndef __STORM__
  1031.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  1032. #else
  1033.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  1034. #endif
  1035.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  1036.       if (ctx->RasterMask & ALPHABUF_BIT) {
  1037.      ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  1038. #ifndef __STORM__
  1039.      gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  1040. #else
  1041.      gl_write_alpha_span( ctx, n, x, y, (CONST GLubyte(*)[4])rgba, write_all ? Null : mask );
  1042. #endif
  1043.      ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  1044.       }
  1045.    }
  1046. }
  1047.  
  1048.  
  1049.  
  1050. /*
  1051.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  1052.  * reading ouside the buffer's boundaries.
  1053.  */
  1054. void gl_read_rgba_span( GLcontext *ctx,
  1055.             GLuint n, GLint x, GLint y,
  1056.             GLubyte rgba[][4] )
  1057. {
  1058.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  1059.       /* completely above, below, or right */
  1060.       MEMSET( rgba, 0, 4 * n * sizeof(GLubyte)); /*XXX maybe leave undefined?*/
  1061.    }
  1062.    else {
  1063.       GLint skip, length;
  1064.       if (x < 0) {
  1065.      /* left edge clippping */
  1066.      skip = -x;
  1067.      length = (GLint) n - skip;
  1068.      if (length < 0) {
  1069.         /* completely left of window */
  1070.         return;
  1071.      }
  1072.      if (length > ctx->Buffer->Width) {
  1073.         length = ctx->Buffer->Width;
  1074.      }
  1075.       }
  1076.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  1077.      /* right edge clipping */
  1078.      skip = 0;
  1079.      length = ctx->Buffer->Width - x;
  1080.      if (length < 0) {
  1081.         /* completely to right of window */
  1082.         return;
  1083.      }
  1084.       }
  1085.       else {
  1086.      /* no clipping */
  1087.      skip = 0;
  1088.      length = (GLint) n;
  1089.       }
  1090.  
  1091.       (*ctx->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
  1092.       if (ctx->RasterMask & ALPHABUF_BIT) {
  1093.      gl_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
  1094.       }
  1095.    }
  1096. }
  1097.  
  1098.  
  1099.  
  1100.  
  1101. /*
  1102.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  1103.  * reading ouside the buffer's boundaries.
  1104.  */
  1105. void gl_read_index_span( GLcontext *ctx,
  1106.              GLuint n, GLint x, GLint y, GLuint indx[] )
  1107. {
  1108.    register GLuint i;
  1109.  
  1110.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  1111.       /* completely above, below, or right */
  1112.       for (i=0;i<n;i++) {
  1113.      indx[i] = 0;
  1114.       }
  1115.    }
  1116.    else {
  1117.       GLint skip, length;
  1118.       if (x < 0) {
  1119.      /* left edge clippping */
  1120.      skip = -x;
  1121.      length = (GLint) n - skip;
  1122.      if (length < 0) {
  1123.         /* completely left of window */
  1124.         return;
  1125.      }
  1126.      if (length > ctx->Buffer->Width) {
  1127.         length = ctx->Buffer->Width;
  1128.      }
  1129.       }
  1130.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  1131.      /* right edge clipping */
  1132.      skip = 0;
  1133.      length = ctx->Buffer->Width - x;
  1134.      if (length < 0) {
  1135.         /* completely to right of window */
  1136.         return;
  1137.      }
  1138.       }
  1139.       else {
  1140.      /* no clipping */
  1141.      skip = 0;
  1142.      length = (GLint) n;
  1143.       }
  1144.  
  1145.       (*ctx->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
  1146.    }
  1147. }
  1148.